using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Cinemachine;
using UnityEngine;

public class EnemySpawnController : MonoBehaviour
{
    [SerializeField] private SpriteRenderer[] _boundsRenderers;

    [Tooltip("拖入场景中的Cinemachine 2D虚拟相机")]
    public CinemachineVirtualCamera vcam2D;

    [Tooltip("生成位置与镜头边缘的最小距离（避免过近）")]
    public float _edgeOffset = 4f;

    // 虚拟相机当前的可视边界（世界坐标）
    private float _camLeft;
    private float _camRight;
    private float _camTop;
    private float _camBottom;

    private Vector2 _minSpawnBouds;
    private Vector2 _maxSpawnBouds;

    private List<IClearable> _clearableList = new();

    private void Awake()
    {
        GetTotalBounds();
    }
    
    private void OnEnable()
    {
        EventCenter.AddEventListener(EventName.CurrentWaveFinish, ClearAllClearableTarget);
        EventCenter.AddEventListener<GameObject>(EventName.SpawnEnemy, SpawnEnemy);
    }
    
    private void OnDisable()
    {
        EventCenter.RemoveEventListener(EventName.CurrentWaveFinish, ClearAllClearableTarget);
        EventCenter.RemoveEventListener<GameObject>(EventName.SpawnEnemy, SpawnEnemy);
    }
    private void Update()
    {
        // 每帧更新虚拟相机的可视边界（因虚拟相机会跟随目标移动）
        UpdateVirtualCameraBounds();
    }
    private void GetTotalBounds()
    {
        // 初始化总边界为第一个元素的边界
        Bounds totalBounds = _boundsRenderers[0].bounds;

        // 合并所有元素的边界
        foreach (var renderer in _boundsRenderers)
        {
            totalBounds.Encapsulate(renderer.bounds);
        }
        _minSpawnBouds = totalBounds.min;
        _maxSpawnBouds = totalBounds.max;
    }
    /// <summary>
    /// 计算虚拟相机当前的可视边界（世界坐标）
    /// </summary>
    private void UpdateVirtualCameraBounds()
    {
        // 从虚拟相机获取正交参数（2D虚拟相机的正交大小）
        float orthoSize = vcam2D.m_Lens.OrthographicSize;

        // 屏幕宽高比（宽/高）
        float aspectRatio = (float)Screen.width / Screen.height;

        // 虚拟相机的水平可视范围的一半（世界单位）
        float halfWidth = orthoSize * aspectRatio;

        // 虚拟相机的世界位置（因可能跟随玩家移动，需实时获取）
        Vector3 vcamPos = vcam2D.transform.position;

        // 计算边界（世界坐标）
        _camLeft = vcamPos.x - halfWidth;    // 左边界
        _camRight = vcamPos.x + halfWidth;   // 右边界
        _camBottom = vcamPos.y - orthoSize;  // 下边界
        _camTop = vcamPos.y + orthoSize;     // 上边界
    }

    private void SpawnEnemy(GameObject enemyPrefab)
    {
        // 获取镜头外的随机位置
        Vector3 spawnPos = CalculateScreenPosition();
        spawnPos.z = 0;

        GameObject enemy = PoolManager.Instance.Get(enemyPrefab, (enemy) =>
        {
            enemy.transform.position = spawnPos;
            enemy.transform.rotation = Quaternion.identity;
        });
    }
    
    /// <summary>
    /// 计算镜头外的随机位置
    /// </summary>
    private Vector3 CalculateScreenPosition()
    {
        // 随机选择生成方向（上、下、左、右）
        int direction = Random.Range(0, 4);
        Vector3 spawnPos = Vector3.zero;

        switch (direction)
        {
            case 0: // 上方（超出上边界）
                // X在相机水平范围内随机，Y在相机上边界外侧
                spawnPos.x = Random.Range(_camLeft, _camRight);
                spawnPos.y = _camTop + _edgeOffset;
                break;
            case 1: // 下方（超出下边界）
                spawnPos.x = Random.Range(_camLeft, _camRight);
                spawnPos.y = _camBottom - _edgeOffset;
                break;
            case 2: // 左方（超出左边界）
                // Y在相机垂直范围内随机，X在相机左边界外侧
                spawnPos.x = _camLeft - _edgeOffset;
                spawnPos.y = Random.Range(_camBottom, _camTop);
                break;
            case 3: // 右方（超出右边界）
                spawnPos.x = _camRight + _edgeOffset;
                spawnPos.y = Random.Range(_camBottom, _camTop);
                break;
        }
        spawnPos.x = Mathf.Clamp(spawnPos.x, _minSpawnBouds.x,  _maxSpawnBouds.x);
        spawnPos.y = Mathf.Clamp(spawnPos.y, _minSpawnBouds.y, _maxSpawnBouds.y);

        return spawnPos;
    }
    private void ClearAllClearableTarget()
    {
        _clearableList.Clear();

        _clearableList = FindObjectsByType<MonoBehaviour>(FindObjectsInactive.Include, FindObjectsSortMode.None)
                        .OfType<IClearable>().
                        ToList();

        foreach (IClearable clearable in _clearableList)
            clearable.HandleClear();
    }
}
